package com.technology.javase;
//java面向对象 三大特征 封装 继承 多态
              // 继承和实现  抽象类(抽象类可以理解为是一个只有方法声明没有方法体的特殊类。)和接口  接口和抽象类代表就是抽象类型
                         //private static final 无法被重写
/*
* 1、 接口中都是抽象方法
2、 通过interface关键字创建接口
3、 通过implements让子类来实现
4、 可以理解成，接口是一个特殊的抽象类
5、 接口突破了java的单继承的局限性
6、 接口和类之间可以多实现，接口和接口之间可以多继承
7、 接口是对外暴露的规则，是一套开发规范
8、 接口提高了程序的功能扩展，降低了耦合性
* */

/**接口和接口的关系：
 --  继承关系 interface c extends A
 --  多继承  interface c extends A,B*/
public class FaceObject {

    //多态 向上转型(小转大)    向下转型（大转小）
    //主 向上转型时，子类对象当成父类对象，只能调用父类的功能，如果子类重写了父类的方法就根据这个引用指向调用子类重写方法。
    /*
    * 多态特点（必要条件）
    * 1，多态的前提是继承
    * 2，要有方法的重写
    * 3，父类引用指向子类对象  Animal a = new Dog();
    * 4，多态中，编译看左边，运行看右边
    * */

    public static void main(String[] args) {
        show(new Cat());  //以Cat对象调佣show方法
        show(new Dog());  //以Dog对象调用

        Animal a = new Cat(); //向上转型
        a.eat();            //调用的是Cat的eat
        Cat c = (Cat) a;  //向下转型
        c.work();    //调用的是Cat和work

        System.out.println();

        Cat h = new Cat();
        h.work();
        h.eat();
    }

    private static void show(Animal a) {
        a.eat();
        //类型判断
        if (a instanceof Cat){ //猫做的事情
//            ((Cat) a).work();  //当使用多态方式调用方法时，首先检查父类中是否有该方法，如果没有，则编译错误；如果有，再去调用子类的同名方法。
            Cat c = (Cat)a;
            c.work();
        }else if (a instanceof Dog){  //狗做的事情

        }

    }

}
abstract class Animal{
    abstract void eat();
}
class Cat extends Animal{
    public void eat(){
        System.out.println("吃鱼");
    }
    public void work(){
        System.out.println("抓老鼠");
    }
}
class Dog extends Animal{
    public void eat(){
        System.out.println("吃骨头");
    }
    public void work(){
        System.out.println("看家");
    }
    Fruit fruit = new Fruit() {
        @Override
        public void eat() {

        }
    };
//    Fruit fruit1 = new Fruit(); //这是错误的，抽象类是不允许实例化的（new对象），必须指向子类进行创建对象
}
/*
* a:抽象类和抽象方法必须有abstract 关键字修饰
 * abstract class 类名{}
 * public abstract void eat();
* b:抽象类不一定有抽象方法，有抽象方法的类一定是抽象类或者接口
* c:抽象类不能被实例化，那么抽象类如何实例化呢？
 * 按多态的方式，由具体的子类实例化，其实这也是多态的一种，抽象类多态。
* d: 抽象类的子类
 * 要么是抽象类
 * 要么重写抽象类中的所有抽象方法
* */
abstract class Fruit{
    //抽象类中可以没有抽象方法
    public void juice(){
        System.out.println("榨汁");
    }
    /**
     * 有抽象方法之后，子类必须重写该方法
     */
    //Java中可以定义没有方法体的方法，该方法由其子类来具体的实现。该没有方法体的方法我们称之为抽象方法，含有抽象方法的类我们称之为抽象类。
    public abstract void eat(); //抽象方法，没有具体的实现，也就是没有大括号中的内容，只有声明
}
class Apple extends Fruit{
    public void juice(){
        System.out.println("苹果榨汁");
    }
    @Override
    public void eat() {
        System.out.println("吃苹果");
    }
}
abstract class Orange extends Fruit{

}
interface implement {
    //接口里是没有构造方法的。
    //在创建实现类的对象时默认的super()，是调用的默认Object的无参构造。
    //接口里没有成员变量，都是常量。所以，你定义一个变量没有写修饰符时，默认会加上： public static final
}
